local Set = {}
Set.__cname = "util.Set"
Set.__index = Set

function Set.new(tb)
    local obj = {}
    setmetatable(obj, Set)
    obj:ctor(tb)
    return obj
end

function Set:ctor(tb)
    if nil ~= tb then
        local distinctCount = 0
        for k, v in pairs(tb) do
            local flag = self.setTb[v]
            if nil == flag then
                self.setTb[v] = 1
                distinctCount = distinctCount + 1
            end
        end
        self.count = distinctCount
    else
        self.setTb = {}
        self.count = 0
    end
end

function Set:Clear()
    if 0 == self.count then return end
    self.setTb = {}
    self.count = 0
end

function Set:GetCount()
    return self.count
end

function Set:Add(v)
    if nil == v then return false end
    if nil ~= self.setTb[v] then return false end

    self.setTb[v] = 1
    self.count = self.count + 1
    return true
end

function Set:Remove(v)
    if nil == v or 0 == self.count then return false end

    local flag = self.setTb[v]
    if nil ~= flag then
        self.setTb[v] = nil
        self.count = self.count - 1
        return true
    end
    return false
end

function Set:Contains(v)
    if nil == v or 0 == self.count then return false end
    return nil ~= self.setTb[v]
end

---差集
function Set:ExceptWith(other)
    -- 减掉other的所有元素
    assert("util.Set" == other.__cname)

    if self.count < 0 then return end
    if self == other then
        self:Clear()
        return
    end
    for k, v_flag in pairs(other.setTb) do
        self:Remove(k)
    end
end

---交集
function Set:IntersectWith(other)
    -- other有, 自己也有的保留
    assert("util.Set" == other.__cname)

    if 0 == self.count then return end
    if self == other then return end
    if other.count < 1 then
        self:Clear()
        return
    end

    for k, v_flag in pairs(other.setTb) do
        if 1 == self.setTb[k] then
            self.setTb[k] = 2 --other有自己也有的做标记
        end
    end
    --未被标记的删除
    for k, v_flag in pairs(self.setTb) do
        if 2 ~= v_flag then
            self:Remove(k)
        end
    end
end

---并集
function Set:UnionWith(other)
    -- 加上other的所有元素
    assert("util.Set" == other.__cname)

    for k, v_flag in pairs(other.setTb) do
        self:Add(k)
    end
end

---是否为子集
function Set:IsSubsetOf(other)
    -- 自己的元素other都有
    assert("util.Set" == other.__cname)

    if 0 == self.count then return true end --空集是任何集合的子集
    local sameCount = 0
    for k, v_flag in pairs(other.setTb) do
        if nil ~= self.setTb[k] then
            sameCount = sameCount + 1
        end
    end
    return self.count == sameCount
end

---是否为真子集
function Set:IsProperSubsetOf(other)
    -- 自己的元素other都有, 且other有额外的元素
    assert("util.Set" == other.__cname)

    if 0 == self.count then
        if other:GetCount() > 0 then return true end
    end

    local sameCount = 0
    local differentCount = 0
    for k, v_flag in pairs(other.setTb) do
        if nil ~= self.setTb[k] then
            sameCount = sameCount + 1
        else
            differentCount = differentCount + 1
        end
    end
    return self.count == sameCount and differentCount > 0
end

---是否为超集
function Set:IsSupersetOf(other)
    -- other的元素自己都有
    assert("util.Set" == other.__cname)

    if 0 == self.count then
        local otherCount = other:GetCount()
        if otherCount < 1 then return true end
        if otherCount > 0 then
            return false
        end
    end

    for k, v_flag in pairs(other.setTb) do
        if nil == self.setTb[k] then --只要other的元素自己没有, 则为false
            return false
        end
    end
    return true
end

---是否为真超集
function Set:IsProperSupersetOf(other)
    -- other的所有元素, 自己都有, 且自己还有额外的元素
    assert("util.Set" == other.__cname)

    if 0 == self.count then return false end
    local otherCount = other:GetCount()
    if otherCount < 1 then return true end

    for k, v_flag in pairs(other.setTb) do
        if nil == self.setTb[k] then --other中有元素自己没有, 则为false
            return false
        end
    end
    return self.count > otherCount
end

---存在重叠(交集)
function Set:IsOverlaps(other)
    --other的元素我有一个就行
    assert("util.Set" == other.__cname)

    if 0 == self.count then return false end
    for k, v_flag in pairs(other.setTb) do
        if self.setTb[k] then
            return true
        end
    end
    return false
end

---两个Set是否相同
function Set:IsEquals(other)
    assert("util.Set" == other.__cname)
    if self.count ~= other.count then return false end

    for k, v_flag in pairs(other.setTb) do
        if not self:Contains(k) then
            return false
        end
    end
    return true
end

function Set:__tostring()
    if 0 == self.count then return "" end
    local strTb = {}
    for k, v_flag in pairs(self.setTb) do
        table.insert(strTb, tostring(k))
    end
    return table.concat(strTb, ",")
end

function Set:GetIterator()
    local function iterator(tb, key)
        local k = next(self.setTb, key)
        return k
    end
    return iterator
end

return Set